package com.core.jdbc;

import com.core.comment.BeanUtil;
import com.core.jdbc.annotate.MySelect;
import com.core.jdbc.annotate.MyUpdate;
import org.quartz.SimpleTrigger;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MySqlAopHandle<T> implements InvocationHandler {

    private T cObject;

    public MySqlAopHandle() {

    }

    public MySqlAopHandle(T o) {
        cObject = o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MySelect mySelect = method.getAnnotation(MySelect.class);
        if (mySelect != null) {
            return select(mySelect, method, args);
        }
        MyUpdate myUpdate = method.getAnnotation(MyUpdate.class);
        if (myUpdate != null) {
            return update(myUpdate, method, args);
        }

        return null;
    }

    private Object select(MySelect mySelect, Method method, Object[] args) throws SQLException {
        Parameter[] parameters = method.getParameters();
        String sql = mySelect.value();
        System.out.println("myselect:" + sql);
        Map<String, Object> par = new HashMap<>();

        for (int i = 0; i < parameters.length; i++) {
            String type = parameters[i].getType().getSimpleName();
            String name = parameters[i].getName();
            if ("Map".equals(type) || "HsahMap".equals(type)) {
                par.putAll((Map) args[i]);
            } else {

                par.put(name, args[i]);
            }
        }
        System.out.println();
        List<Map<String, Object>> list = SqlHelper.queryMapList(sql, par);

        System.out.println(method.getReturnType() == List.class);
        if (method.getReturnType().getSimpleName().equals("List")) {
            return list;
        }
        return null;
    }

    private boolean isBaseType(Class<?> clazz) {
        boolean is = (clazz == byte.class
                || clazz == Integer.class
                || clazz == Long.class
                || clazz == Float.class
                || clazz == Double.class
                || clazz == char.class
                || clazz == boolean.class
                || clazz == Short.class
                || clazz == String.class);
        return is;
    }

    private long update(MyUpdate myUpdate, Method method, Object[] args) throws Exception {
        Parameter[] parameters = method.getParameters();
        String sql = myUpdate.value();
        System.out.println("myupdate:" + sql);
        Map<String, Object> par = new HashMap<>();
        for (int i = 0; i < parameters.length; i++) {
            Class clazz = parameters[i].getType();
            String type = parameters[i].getType().getSimpleName();
            String name = parameters[i].getName();

            if ("Map".equals(type) || "HsahMap".equals(type)) {
                par.putAll((Map) args[i]);
            } else if (!isBaseType(clazz)) {
                par.putAll(BeanUtil.bean2map(args[i]));
            } else {
                par.put(name, args[i]);
            }
        }

        long o = (long) SqlHelper.sqlOperate(sql, par);
        return o;
    }


    public static String tranBeanUpdate(Object obj, Object objTrue, Map<String, Object> par) {

        try {

            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!"class".equals(key)) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Method setter = property.getWriteMethod();
                    Object value = getter.invoke(obj);
                    if (value != null) {
                        setter.invoke(objTrue, value);
                    }
                }
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void before() {
        System.out.println("before");
    }

    public void after() {
        System.out.println("after");
    }
}
